import {isNumber} from '@/utils/number_utils.js'
import {stringIsNull} from '@/utils/string_utils.js'
import {isFunction} from "@/utils/function_utils.js"

/**
 * 禁止页面滚动
 */
export function disabledBodyScroll() {
    const eventHandler = (e) => {
    }
    document.body.style.overflow = 'hidden' // 禁止页面滑动滚动，禁止滚动条出现
    // 监听 touchmove（触摸移动） 事件，啥也不干
    document.addEventListener('touchmove', eventHandler)
}

/**
 * 开启恢复页面滚动
 */
export function enabledBodyScroll() {
    const eventHandler = (e) => {
    }
    document.body.style.overflow = '' // 允许页面滑动滚动，允许滚动条出现
    // 移除监听 touchmove（触摸移动） 事件
    document.removeEventListener('touchmove', eventHandler)
}

/**
 * 获取浏览器可视窗口的高度（兼容所有浏览器）
 * @returns {number} 浏览器可视窗口的高度
 */
export function getBrowserViewHeight() {
    return window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
}

/**
 * 获取浏览器可视窗口的宽度（兼容所有浏览器）
 * @returns {number} 浏览器可视窗口的宽度
 */
export function getBrowserViewWidth() {
    return window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth
}

/**
 * 网页页面滚动到指定的位置，距离单位 px
 * @param position 滚动到的位置
 */
export function webPageRollTo(position) {
    if (!isNumber(position)) throw new TypeError("传入的参数 rollHeight 不为 Number 类型")
    // 网页页面向下滚动到指定的位置
    document.body.scrollTop = position
    document.documentElement.scrollTop = position
}

/**
 * 网页页面平滑滚动到指定的位置，距离单位 px
 * @param position 滚动到的位置
 */
export function webPageRollToSmooth(position) {
    if (!isNumber(position)) throw new TypeError("传入的参数 rollHeight 不为 Number 类型")
    // 网页页面向下平滑滚动到指定的位置
    window.scroll({
        top: position,
        behavior: 'smooth'
    });
}

/**
 * 将指定的元素滚动到可视区域（平滑滚动）
 * @param eleSelector 指定元素的选择器
 */
export function eleScrollIntoViewWithTransition(eleSelector) {
    if (stringIsNull(eleSelector)) throw new TypeError("传入的参数 eleSelector 为空")
    const ele = document.querySelector(eleSelector) // 获取指定元素
    ele.scrollIntoView({behavior: "smooth"}) // 指定的元素滚动到可视区域
}

/**
 * （兼容）获取当前页面滚动条距离顶部的位置
 * 代码来源自：https://blog.csdn.net/huang_rui_min/article/details/131125252
 * @returns {number} 当前页面滚动条距离顶部的位置，单位 px
 */
export function getScrollTop() {
    return document.documentElement ? document.documentElement.scrollTop : document.body.scrollTop
}

/**
 * 网页添加的上滚动的处理事件列表
 * @type {{}}
 */
const scrollUpHandlerList = {}

/**
 * 网页添加的下滚动的处理事件列表
 * @type {{}}
 */
const scrollDownHandlerList = {}

/**
 * 为网页添加上下滚动的处理事件
 * 代码参考自：https://blog.csdn.net/huang_rui_min/article/details/131125252
 * @param scrollUpHandler 上滚动的处理事件
 * @param scrollDownHandler 下滚动的处理事件
 */
export function addDocWheelScrollHandler(
    scrollUpHandler = () => {},
    scrollDownHandler = () => {}
) {
    // 判断是否为函数
    if (!isFunction(scrollUpHandler) || !isFunction(scrollDownHandler)) {
        throw new TypeError("参数 scrollUpHandler 或 scrollDownHandler 不为函数")
    }
    scrollUpHandlerList[scrollUpHandler] = scrollUpHandler
    scrollDownHandlerList[scrollDownHandler] = scrollDownHandler
    let beforeTop = 0 // 记录之前滚动条的位置（默认顶部）
    // 页面添加滚动处理函数
    window.addEventListener('scroll', () => {
        // 兼容，获取当前页面滚动条的位置
        let afterTop = getScrollTop()
        if (afterTop - beforeTop > 0) { // 向下滚动
            for (let scrollDownHandlerListKey in scrollDownHandlerList) {
                scrollDownHandlerList[scrollDownHandlerListKey]()
            }
        } else { // 向上滚动
            for (let scrollUpHandlerListKey in scrollUpHandlerList) {
                scrollUpHandlerList[scrollUpHandlerListKey]()
            }
        }
        // 更新记录上一次（之前）滚动条的位置
        beforeTop = afterTop
    })
}

/**
 * 移除指定的网页上下滚动的处理事件
 * @param scrollUpHandler 上滚动的处理事件
 * @param scrollDownHandler 下滚动的处理事件
 */
export function removeDocWheelScrollHandler(
    scrollUpHandler = () => {},
    scrollDownHandler = () => {}
) {
    // 判断是否为函数
    if (!isFunction(scrollUpHandler) || !isFunction(scrollDownHandler)) {
        throw new TypeError("参数 scrollUpHandler 或 scrollDownHandler 不为函数")
    }
    Reflect.deleteProperty(scrollUpHandlerList, scrollUpHandler)
    Reflect.deleteProperty(scrollDownHandlerList, scrollDownHandler)
}